package com.quanyan.stadium.service.gameRules.impl;

import com.alibaba.dubbo.common.utils.CollectionUtils;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.quanyan.club.entity.RespClubPlainInfo;
import com.quanyan.common.exception.BizException;
import com.quanyan.common.utils.DateUtils;
import com.quanyan.redisCluster.utils.RedisConstants;
import com.quanyan.redisCluster.utils.RedisKey;
import com.quanyan.stadium.api.req.ReqChallenge;
import com.quanyan.stadium.api.req.ReqGompListTimeAndPlace;
import com.quanyan.stadium.biz.BizGameSystemDao;
import com.quanyan.stadium.biz.redis.GameCacheDao;
import com.quanyan.stadium.component.cache.MyRedisTemplate;
import com.quanyan.stadium.component.cache.StadiumRedisConstants;
import com.quanyan.stadium.constants.GameConstants;
import com.quanyan.stadium.entity.*;
import com.quanyan.stadium.entity.vo.*;
import com.quanyan.stadium.enums.GameSystemConfigEnum;
import com.quanyan.stadium.enums.errorEnum.CreateCompListErrorEnum;
import com.quanyan.stadium.mapper.TbGameScheduleAddendumMapper;
import com.quanyan.stadium.mapper.TbTeamDoubleAddendumMapper;
import com.quanyan.stadium.service.commonComponent.BaseService;
import com.quanyan.stadium.service.commonComponent.DataReductionService;
import com.quanyan.stadium.service.commonComponent.OfficialGameCache;
import com.quanyan.stadium.service.gameRules.*;
import com.quanyan.stadium.service.gameRules.GameScheduleService;
import com.quanyan.stadium.transfer.GameConfigTransfer;
import com.quanyan.stadium.utils.GameUtils;
import com.quanyan.user.response.RespUserInfoBase;
import org.apache.commons.beanutils.BeanUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.InvocationTargetException;
import java.util.*;

/**
 * @author songzj
 * @date 16/4/11-14:42
 */

@Service("gameRoundService")
public class GameRoundServiceImpl implements GameRoundService {

    @Autowired
    private BizGameSystemDao bizGameSystemDao;

    @Autowired
    private GameSystemService gameSystemService;

    @Autowired
    private TbTeamDoubleAddendumMapper tbTeamDoubleAddendumMapper;

    @Autowired
    private BaseService baseService;

    @Autowired
    private GameSystemServiceEight gameSystemServiceEight;

    @Autowired
    private GameSystemServiceUnset gameSystemServiceUnset;


    @Autowired
    private GameScheduleService gameScheduleService;

    @Autowired
    private TbGameScheduleAddendumMapper tbGameScheduleAddendumMapper;

    @Autowired
    private DataReductionService dataReductionService;

    @Autowired
    private GameCacheDao gameCacheDao;

    @Autowired
    private OfficialGameCache officialGameCache;

    @Autowired
    private MyRedisTemplate myRedisTemplate;

    @Autowired
    private GameConfigTransfer gameEventTransfer;


    private static final Logger logger = org.slf4j.LoggerFactory.getLogger(GameRoundServiceImpl.class);


    /**
     *
     * 根据赛事id,直;
     *
     *      淘汰\循环\瑞士\混合\6人\8人
     *
     *
     * */
    @Override
    public List<GameRound> createGameRound(TbGameEvent tbGameEvent) throws Exception {
        List<GameRound> result = null;
        //混合赛必须必须存在分组才能生成所有场次
        if (tbGameEvent.getGameSystemType().intValue() == GameSystemConfigEnum.CONFIG_GAME_TYPE_MIXED.getId()) {
            if (tbGameEvent.getTeamGroupNum() < 1 || tbGameEvent.getRankNum() < 1) {
                return result;
            }
        }
        Integer currentTeams = bizGameSystemDao.countTbGameEventTeamByGameEventId(tbGameEvent.getId());

        // 报名人数2人一下不能编排
        if (tbGameEvent.getSignEndTime().after(new Date()) || currentTeams < 2) {
            return result;
        }

        // 5-8不固定打法
        if (tbGameEvent.getGameSystemType().byteValue() == GameSystemConfigEnum.CONFIG_GAME_TYPE_UNSET_RULE.getId()) {

            if (currentTeams<5 || currentTeams>8) {
                return result;
            }

            //8人抢签赛
        }else if (tbGameEvent.getGameSystemType().byteValue() == GameSystemConfigEnum.CONFIG_GAME_TYPE_EIGHT_RULE.getId()) {
            if (currentTeams != 8) {
                return result;
            }
        }else if (tbGameEvent.getGameSystemType().byteValue() == GameSystemConfigEnum.CONFIG_GAME_TYPE_MIXED.getId()){       //混合赛
        }

        result = this.startCreateTbGameRound(tbGameEvent, currentTeams);
        return result;
    }

    /**
     * 开始创建轮次
     * */
    private List<GameRound> startCreateTbGameRound(TbGameEvent tbGameEvent, Integer currentTeams) throws Exception {
        List<GameRound> result = null;
        int roundNum=0, roundNum1=0,roundNum2 = 0;

        // 是否双打
        if (isDivideTeam(tbGameEvent)) {
            currentTeams = currentTeams/2;
        }
        logger.info("开始编辑轮次,当前赛事ID:{},当前队伍数目:{},当前赛制类型TYPE:{}",tbGameEvent.getId(), currentTeams, tbGameEvent.getGameSystemType());
        if (currentTeams > 0) {
            switch (tbGameEvent.getGameSystemType()) {
                case 1:  // 淘汰
                    roundNum = GameUtils.washedRoundleNum(currentTeams.doubleValue());
                    break;
                case 2: // 循环
                    roundNum = GameUtils.circleRoundNum(currentTeams.doubleValue());
                    break;
                case 3:  // 混合
                    if (null == tbGameEvent.getTeamGroupNum() || null == tbGameEvent.getRankNum() || tbGameEvent.getRankNum() == 0 || tbGameEvent.getTeamGroupNum() ==0) {
                        roundNum = 0;
                        break;
                    }
                    //  先算循环轮次数
                    roundNum1 = GameUtils.circleRoundNum((double) (currentTeams % tbGameEvent.getTeamGroupNum() + currentTeams / tbGameEvent.getTeamGroupNum()));
                    // 淘汰轮次数
                    roundNum2 = GameUtils.washedRoundleNum((double) (tbGameEvent.getTeamGroupNum() * tbGameEvent.getRankNum()));
                    // 求和
                    roundNum = roundNum1 + roundNum2;
                    break;
                case 4:  // 等位
                    roundNum = GameUtils.swissRoundleNum(currentTeams.doubleValue());
                    break;
                case 5:  // 不固定打发
                    roundNum = GameUtils.unsetRoundNum(currentTeams.doubleValue());
                    break;
                case 6:
                    //个人赛 暂无
                    break;
                case 7:  // 8人抢签
                    roundNum = GameUtils.eightRoundleNum();
                    break;
                default:
                    return null;
            }
            //生成轮次
            result = this.startTransTbGameRoundToGameRound(this.generateTbGameRound(tbGameEvent, roundNum, roundNum1, roundNum2, currentTeams), tbGameEvent);
        }
        return result;
    }

    /**
     * 对轮次的数据进行封装处理并放入缓存
     *
     * */
    private List<GameRound> startTransTbGameRoundToGameRound(List<TbGameRound> resultTemp, TbGameEvent tbGameEvent) throws InvocationTargetException, IllegalAccessException {
        List<GameRound> result = null;
        if (null != resultTemp && resultTemp.size() > 0) {
            result = new ArrayList<>();
            for (TbGameRound round : resultTemp) {
                result.add(officialGameCache.getGameRound(round.getId()));
            }
        }
        return result;
    }



    @Override
    public List<TbGameRound> generateTbGameRound(TbGameEvent tbGameEvent, Integer roundNum, Integer roundNum1, Integer roundNum2, Integer currentTeams) throws Exception {
        List<TbGameRound> resultTemp = bizGameSystemDao.selectTbGameRoundByGameEventId(tbGameEvent.getId());
        if (null == resultTemp || resultTemp.size() < 1) {
            RedisKey redisKey = new RedisKey(RedisConstants.STADIUM_FAMILY_KEY, StadiumRedisConstants.getGameRoundGeneratingKey(tbGameEvent.getId()));
            long flag = myRedisTemplate.setnx(redisKey);
            if (flag == 0) {
                return resultTemp;
            }
            try{
                int nextTeams = tbGameEvent.getTeamGroupNum() * tbGameEvent.getRankNum();
                int rankWash = (int)Math.pow(2, GameUtils.washedRoundleNum((double) currentTeams))/2;
                int rankMix = (int)Math.pow(2, GameUtils.washedRoundleNum((double) nextTeams))/2;
                for (int i=0; i < roundNum; i++) {
                    TbGameRound gameRound = new TbGameRound();
                    if (roundNum1 > 0 && roundNum2 > 0) {  //混合
                        if (i >= roundNum1) {
                            if (i==roundNum1) {
                                gameRound.setCurrentTeamNum(nextTeams);
                                gameRound.setRankTeamNum(rankMix);
                            }else{
                                gameRound.setCurrentTeamNum(rankMix);
                                gameRound.setRankTeamNum(rankMix/2);
                                rankMix = rankMix/2;
                            }
                            gameRound.setName(GameSystemConfigEnum.CONFIG_GAME_TYPE_WASHED.getLabel());
                        }else {
                            gameRound.setCurrentTeamNum(currentTeams);
                            gameRound.setRankTeamNum(currentTeams);
                            gameRound.setName(GameSystemConfigEnum.CONFIG_GAME_TYPE_CIRCLE.getLabel());
                        }
                        gameRound.setRoundStatus((byte) (i+1));
                    } else {
                        if (tbGameEvent.getGameSystemType().intValue() == GameSystemConfigEnum.CONFIG_GAME_TYPE_WASHED.getId()) {  //淘汰
                            if (i== 0) {
                                gameRound.setCurrentTeamNum(currentTeams);
                                gameRound.setRankTeamNum(rankWash);
                            }else{
                                gameRound.setCurrentTeamNum(rankWash);
                                gameRound.setRankTeamNum(rankWash/2);
                                rankWash = rankWash/2;
                            }
                        }else {
                            gameRound.setCurrentTeamNum(currentTeams);
                            gameRound.setRankTeamNum(currentTeams);
                        }
                        gameRound.setName(gameEventTransfer.getGameSystemById(tbGameEvent.getGameSystemType().intValue()).getName());
                        gameRound.setRoundStatus((byte) (i + 1));
                    }
                    gameRound.setGameEventId(tbGameEvent.getId());
                    gameRound.setPlaceId(tbGameEvent.getPlaceId());
                    if (null == bizGameSystemDao.insertTbGameRound(gameRound).getId()) {
                        throw new Exception("数据库异常");
                    }
                }
            }catch (Exception e) {
                logger.debug("generateTbGameRound异常, 原因:{}", e);
            }finally {
                myRedisTemplate.delteKey(redisKey);
            }
            resultTemp  = bizGameSystemDao.selectTbGameRoundByGameEventId(tbGameEvent.getId());
        }
        return resultTemp;
    }


    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public List<GameSchedule> generateCompList(ReqChallenge reqChallenge) throws Exception {
        TbGameEvent tbGameEvent = bizGameSystemDao.selectTbGameEvent(reqChallenge.getGameEventId());
        //设置双打
        if (gameEventTransfer.getGameCategoryById(tbGameEvent.getGameCategoryType().intValue()).getMinNum() == 2
                && gameEventTransfer.getGameCategoryById(tbGameEvent.getGameCategoryType().intValue()).getMaxNum() == 2) {
            reqChallenge.setIsDouble(true);
        }
        List<TbGameRound> tbGameRoundList = bizGameSystemDao.selectTbGameRoundByGameEventId(reqChallenge.getGameEventId());
        List<TbGameEventTeam> tbGameEventTeamList = bizGameSystemDao.selectTbGameEventTeamByGameEventId(reqChallenge.getGameEventId(), null, null, GameConstants.IS_NOT_DELETE);
        Integer preGameRoundId = 0;
        TbGameRound preTbGameRound =  new TbGameRound();
        TbGameRound currentTbGameRound =  new TbGameRound();
        boolean isLegal = false;
        int i=0;
        for (TbGameRound roundTemp : tbGameRoundList) {    //校验轮次合法性,更新轮次的时间
            if ((reqChallenge.getGameRoundId().compareTo(roundTemp.getId()) == 0)) {
                isLegal = true;
                currentTbGameRound = roundTemp;
                if (i>0) {
                    preTbGameRound = tbGameRoundList.get(i-1);
                    preGameRoundId = tbGameRoundList.get(i-1).getId();
                }
                break;
            }
            i++;
        }
        if (!isLegal) {
            throw new BizException(null, CreateCompListErrorEnum.CREATE_COMP_LIST_ERROR_8.getLabel());
        }
        if (null != currentTbGameRound && currentTbGameRound.getIsArrange().intValue() == GameConstants.IS_NOT_DELETE.intValue()) {
            int flag = this.validateCreateTbGameScheduleParam(tbGameRoundList, tbGameEventTeamList, reqChallenge, preGameRoundId, currentTbGameRound, tbGameEvent);
            if (flag!=0) {
                throw new BizException(null, CreateCompListErrorEnum.getMsgById(flag));
            }
            //更新上一轮轮次状态，更新数据库与缓存
            if (preGameRoundId>0) {
                TbGameRound preGameRound = new TbGameRound();
                preGameRound.setId(preGameRoundId);
                preGameRound.setIsEnd(GameConstants.IS_DELETE);
                bizGameSystemDao.updateTbGameRound(preGameRound);

                officialGameCache.delGameRound(preGameRoundId);
            }
            currentTbGameRound.setIsArrange(GameConstants.IS_NOT_DELETE);
        }

        //start create schedule
        List<VDefinedGameSchedule> vDefinedGameSchedules = this.startCreateTbGameSchedule(reqChallenge, tbGameRoundList, tbGameEventTeamList, tbGameEvent, preGameRoundId);
        if (vDefinedGameSchedules == null || vDefinedGameSchedules.size() < 1) {
            throw new BizException(null, CreateCompListErrorEnum.CREATE_COMP_LIST_ERROR_5.getLabel());
        }


        List<GameSchedule> result = this.transferTbGameSchedule2GameSchedule(vDefinedGameSchedules, tbGameEvent.getGameTeamType().intValue(), currentTbGameRound);
        if (null != currentTbGameRound && currentTbGameRound.getIsArrange().intValue() == GameConstants.IS_NOT_DELETE.intValue()) {
            //mq
            dataReductionService.generateCurrentRoundMQ(preTbGameRound, currentTbGameRound, tbGameEvent, false);
            logger.info("轮次id:{}的赛程才创建成功,批量调起mq", currentTbGameRound.getId());

            gameCacheDao.initGameScheduleToCache(result);
            logger.info("轮次id:{}的赛程才创建成功,批量添加到缓存", currentTbGameRound.getId());
        }

        return result;
    }

    @Override
    public int  validateCreateTbGameScheduleParam(List<TbGameRound> tbGameRoundList, List<TbGameEventTeam> tbGameEventTeamList, ReqChallenge reqChallenge,
                                                 Integer preGameRoundId, TbGameRound currentTbGameRound, TbGameEvent tbGameEvent) {
        if (null == tbGameRoundList || null == tbGameEventTeamList) {
            return CreateCompListErrorEnum.CREATE_COMP_LIST_ERROR_7.getId();
        }
        if (tbGameEventTeamList.size() < 1 || tbGameRoundList.size() < 1) {  //校验队伍合法性
            return CreateCompListErrorEnum.CREATE_COMP_LIST_ERROR_5.getId();
        }
        if (reqChallenge.getIsArrange().byteValue() == GameConstants.IS_DELETE) {  //校验存在编排的赛事
            if (null == reqChallenge.getReqGompListTimeAndPlaces() || reqChallenge.getReqGompListTimeAndPlaces().size() < 1) {
                return CreateCompListErrorEnum.CREATE_COMP_LIST_ERROR_1.getId();
            }
            for (ReqGompListTimeAndPlace req : reqChallenge.getReqGompListTimeAndPlaces()) {
                if (req.getStartTime()<new Date().getTime() || req.getEndTime() <= req.getStartTime() ||
                        (null != req.getSingleTime() &&req.getEndTime() - req.getStartTime() < req.getSingleTime() * 60 * 1000)) {
                    return CreateCompListErrorEnum.CREATE_COMP_LIST_ERROR_2.getId();
                }
            }

        }else {
            if (null!=reqChallenge.getReqGompListTimeAndPlaces() && reqChallenge.getReqGompListTimeAndPlaces().size() > 0) {
                long startTime = reqChallenge.getReqGompListTimeAndPlaces().get(0).getStartTime();
                long endTime = reqChallenge.getReqGompListTimeAndPlaces().get(0).getEndTime();
                if (startTime<new Date().getTime() || endTime<=startTime) {
                    return CreateCompListErrorEnum.CREATE_COMP_LIST_ERROR_2.getId();
                }
            }
        }
        if (preGameRoundId != 0) { //校验上一轮的赛程是否录入全部有效(冲突时候停止,其他情况返回)
            List<TbGameSchedule> tbGameScheduleList = bizGameSystemDao.selectTbGameScheduleByGameRoundId(preGameRoundId, null, null);
            for (TbGameSchedule tbGameSchedule : tbGameScheduleList) {
                if (tbGameSchedule.getStatus().intValue() == GameConstants.RECORD_FAIL.intValue() ||
                        tbGameSchedule.getStatus().intValue() == GameConstants.RECORD_WAIT.intValue() ||
                        tbGameSchedule.getStatus().intValue() == GameConstants.RECORD_WAIT_SURE.intValue()) {
                    return CreateCompListErrorEnum.CREATE_COMP_LIST_ERROR_3.getId();
                }
                tbGameSchedule.setStatus(GameConstants.RECORD_SUCCESS);
                bizGameSystemDao.updateTbGameSchedule(tbGameSchedule);
            }
        }
        if (preGameRoundId!=0 && currentTbGameRound.getIsGenerate().intValue() == GameConstants.IS_NOT_DELETE.intValue()) {
            RedisKey redisKey = new RedisKey(RedisConstants.STADIUM_FAMILY_KEY, StadiumRedisConstants.getGameScheduleGeneratingKey(preGameRoundId));
            long flag = myRedisTemplate.setnx(redisKey);
            if (flag == 0) {
                return CreateCompListErrorEnum.CREATE_COMP_LIST_ERROR_10.getId();
            }
            boolean validateRecordScore = gameScheduleService.recordGameRoundTeamScore(tbGameEvent, preGameRoundId, tbGameRoundList, tbGameEventTeamList);
            myRedisTemplate.delteKey(redisKey);
            if (!validateRecordScore) {          //轮次积分 录入
                return CreateCompListErrorEnum.CREATE_COMP_LIST_ERROR_4.getId();
            }
        }
        return 0;
    }


    /**
     * 开始创建赛程
     *
     * */
    public List<VDefinedGameSchedule> startCreateTbGameSchedule(ReqChallenge reqChallenge,  List<TbGameRound> tbGameRoundList , List<TbGameEventTeam> tbGameEventTeamList,
                                                                 TbGameEvent tbGameEvent, Integer preGameRoundId) throws Exception {
        List<VDefinedGameSchedule> vDefinedGameSchedules = new ArrayList<>();
        Collections.sort(tbGameEventTeamList, new Comparator<TbGameEventTeam>() {
            public int compare(TbGameEventTeam o1, TbGameEventTeam o2) {
                return o2.getScore().compareTo(o1.getScore());
            }
        });

        //对逻辑映射
        List<Integer> teamIds = new ArrayList<>();
        for (TbGameEventTeam tbGameEventTeam : tbGameEventTeamList) { //队伍id集合
            teamIds.add(tbGameEventTeam.getId());
        }
        if (reqChallenge.getIsDouble()) {
            TbTeamDoubleAddendumExample example = new TbTeamDoubleAddendumExample();
            TbTeamDoubleAddendumExample.Criteria criteria = example.createCriteria();
            criteria.andGameEventIdEqualTo(reqChallenge.getGameEventId());
            criteria.andIsDeleteEqualTo(GameConstants.IS_NOT_DELETE);
            List<TbTeamDoubleAddendum> list = tbTeamDoubleAddendumMapper.selectByExample(example);
            reqChallenge.setTbTeamDoubleAddendumList(list);
        }
        //赛制传递
        reqChallenge.setGameSystemType(tbGameEvent.getGameSystemType());

        logger.info("开始生成对战表,当前赛事ID:{},当前队伍数目:{},当前赛制类型TYPE:{}",tbGameEvent.getId(), teamIds.size(), tbGameEvent.getGameSystemType());
        switch (tbGameEvent.getGameSystemType()) {
            case 1:
                vDefinedGameSchedules = this.generateWashedCompList(tbGameRoundList, teamIds, reqChallenge, preGameRoundId);
                break;
            case 2:
                vDefinedGameSchedules = this.generateCircleCompList(tbGameRoundList, teamIds, reqChallenge, tbGameEvent.getGameTeamType().intValue());
                break;
            case 3:
                vDefinedGameSchedules = this.generateMixedCompList(tbGameRoundList, teamIds, reqChallenge, preGameRoundId);
                break;
            case 4:
                vDefinedGameSchedules = this.generateSwissCompList(tbGameRoundList, teamIds, reqChallenge, preGameRoundId);
                break;
            case 5:
                vDefinedGameSchedules = this.generateUnsetCompList(teamIds, reqChallenge, preGameRoundId);
                break;
            case 6:
                //个人赛
                break;
            case 7:
                vDefinedGameSchedules = this.generateEightCompList(teamIds, reqChallenge, preGameRoundId);
                break;
            default:
                logger.debug("赛制不存在");
        }
        return vDefinedGameSchedules;
    }

    @Override
    public List<VDefinedGameSchedule> generateScheduleAndUpdateRound(Integer type, List<GameGroup> gameGroups, Integer currentGameRoundId, ReqChallenge reqChallenge) {
        if (type == 0) {
            if (null == gameGroups || gameGroups.size() < 1) {                   //校验list的合法性
                return null;
            }
            for (GameGroup group : gameGroups) {
                TbGameSchedule schedule = new TbGameSchedule();
                schedule.setGameRoundId(group.getGameRoundId());
                schedule.setGroupType(group.getGroup().byteValue());
                if (group.getIsWin() || (null!=group.getTeamAwayId() && group.getTeamAwayId().intValue() == 0)) { //校验出现轮空的情况
                    schedule.setIsWin(GameConstants.IS_DELETE);
                    schedule.setStatus(GameConstants.RECORD_SUCCESS);
                    schedule.setIsEnd(GameConstants.IS_DELETE);
                    schedule.setFinalScore("1:0");
                }
                TbGameSchedule scheduleTemp = bizGameSystemDao.insertTbGameSchedule(schedule); //插入记录 对战记录
                if (reqChallenge.getIsDouble()) {
                    List<TbTeamDoubleAddendum> temp = reqChallenge.getTbTeamDoubleAddendumList();
                    Map<Integer, TbTeamDoubleAddendum> addendumMap = new HashMap<>();
                    for (TbTeamDoubleAddendum tbTeamDoubleAddendum : temp) {
                        addendumMap.put(tbTeamDoubleAddendum.getId(), tbTeamDoubleAddendum);
                    }

                    Gson gson = new Gson();
                    List<Integer> gameEventHomeTeamIds = gson.fromJson(addendumMap.get(group.getTeamHomeId()).getTeamIdGson() ,new TypeToken<List<Integer>>() {
                    }.getType());
                    for (Integer tempInt :gameEventHomeTeamIds) {
                        TbGameScheduleAddendum addendum1 = new TbGameScheduleAddendum();
                        addendum1.setGameScheduleId(scheduleTemp.getId());
                        addendum1.setType((byte) 0);
                        addendum1.setEventTeamId(tempInt);
                        tbGameScheduleAddendumMapper.insertSelective(addendum1);
                    }

                    List<Integer> gameEventAwayTeamIds = new ArrayList<>();
                    gameEventAwayTeamIds.add(0);
                    if (null!=group.getTeamAwayId() && group.getTeamAwayId() != 0) {   //轮空逻辑处理
                        gameEventAwayTeamIds = gson.fromJson(addendumMap.get(group.getTeamAwayId()).getTeamIdGson() ,new TypeToken<List<Integer>>() {
                        }.getType());
                    }
                    for (Integer tempInt :gameEventAwayTeamIds) {
                        TbGameScheduleAddendum addendum2 = new TbGameScheduleAddendum();
                        addendum2.setGameScheduleId(scheduleTemp.getId());
                        addendum2.setType((byte) 1);
                        addendum2.setEventTeamId(tempInt);
                        tbGameScheduleAddendumMapper.insertSelective(addendum2);
                    }

                }else {
                    TbGameScheduleAddendum addendum1 = new TbGameScheduleAddendum();
                    addendum1.setGameScheduleId(scheduleTemp.getId());
                    addendum1.setType((byte) 0);
                    addendum1.setEventTeamId(group.getTeamHomeId());
                    TbGameScheduleAddendum addendum2 = new TbGameScheduleAddendum();
                    addendum2.setGameScheduleId(scheduleTemp.getId());
                    addendum2.setType((byte) 1);
                    addendum2.setEventTeamId(group.getTeamAwayId());
                    tbGameScheduleAddendumMapper.insertSelective(addendum1);
                    tbGameScheduleAddendumMapper.insertSelective(addendum2);
                }
            }
        }
        //this.updateScheduleTimeAndPlaceUnit(currentGameRoundId, reqChallenge);   //更新时间
        return bizGameSystemDao.selectVDefinedGameScheduleByGameRoundId(currentGameRoundId, null, null);
    }

    @Override
    public void updateScheduleTimeAndPlaceUnit(Integer currentGameRoundId, ReqChallenge reqChallenge) {
        List<ReqGompListTimeAndPlace> reqList = reqChallenge.getReqGompListTimeAndPlaces();
        TbGameRound tbGameRound = bizGameSystemDao.selectTbGameRound(currentGameRoundId);
        if (tbGameRound.getIsGenerate().byteValue() == GameConstants.IS_DELETE || null == reqList || reqList.size() < 1) {  //直接返回
            return;
        }
        List<TbGameSchedule> schedules = bizGameSystemDao.selectTbGameScheduleByGameRoundId(currentGameRoundId, null, null);
        ReqGompListTimeAndPlace reqGompListTimeAndPlace = reqList.get(0);
        long roundStartTime = reqGompListTimeAndPlace.getStartTime(), roundEndTime = reqGompListTimeAndPlace.getEndTime();
        for (TbGameSchedule tbGameSchedule : schedules) {   //时间初始化
            TbGameSchedule temp = new TbGameSchedule();
            temp.setId(tbGameSchedule.getId());
            temp.setStartTime(new Date(roundStartTime));
            temp.setEndTime(new Date(roundEndTime));
            bizGameSystemDao.updateTbGameSchedule(temp);
        }
        if (reqChallenge.getIsArrange() == 1) {
            List<TbGameSchedule> scheduleTemp = new ArrayList<>();
            int n = schedules.size(),i=0;
            boolean flag = false;
            for (ReqGompListTimeAndPlace req : reqList) {
                if (req.getStartTime() < roundStartTime) {
                    roundStartTime = req.getStartTime();
                }
                if (req.getEndTime() > roundEndTime) {
                    roundEndTime = req.getEndTime();
                }
                Long endTime = req.getEndTime(),startTime =req.getStartTime();
                int sigleTime = req.getSingleTime();
                while (endTime > startTime) {
                    i+=req.getPlaceUnitIdList().size();
                    if (i <= n) {
                        for (Integer integer :req.getPlaceUnitIdList()) {
                            TbGameSchedule schedule = new TbGameSchedule();
                            schedule.setStartTime(new Date(startTime));
                            schedule.setEndTime(DateUtils.addTime(new Date(startTime), sigleTime, DateUtils.TIME_TYPE_MINUTE));
                            schedule.setPlaceUnitId(integer);
                            schedule.setSingleTime(req.getSingleTime());
                            scheduleTemp.add(schedule);
                        }
                    }else if (i> n && i-req.getPlaceUnitIdList().size()<n) {
                        for (int j=0;j<i-n;j++) {
                            TbGameSchedule schedule = new TbGameSchedule();
                            schedule.setStartTime(new Date(startTime));
                            schedule.setEndTime(DateUtils.addTime(new Date(startTime), sigleTime, DateUtils.TIME_TYPE_MINUTE));
                            schedule.setPlaceUnitId(req.getPlaceUnitIdList().get(j));
                            schedule.setSingleTime(req.getSingleTime());
                            scheduleTemp.add(schedule);
                        }
                        i=n;
                    }else {
                        //直接跳出
                        flag =true;
                        break;
                    }
                    startTime = DateUtils.addTime(new Date(startTime), sigleTime, DateUtils.TIME_TYPE_MINUTE).getTime();
                }
                if (flag) break;
            }
            for (i=0;i<scheduleTemp.size();i++) {
                TbGameSchedule tbGameSchedule = new TbGameSchedule();
                tbGameSchedule.setId(schedules.get(i).getId());
                tbGameSchedule.setStartTime(scheduleTemp.get(i).getStartTime());
                tbGameSchedule.setEndTime(scheduleTemp.get(i).getEndTime());
                tbGameSchedule.setPlaceUnitId(scheduleTemp.get(i).getPlaceUnitId());
                tbGameSchedule.setSingleTime(scheduleTemp.get(i).getSingleTime());
                bizGameSystemDao.updateTbGameSchedule(tbGameSchedule);
            }
        }
        TbGameRound tempRound = new TbGameRound();                              //更新轮次状态,对战表生产
        tempRound.setId(currentGameRoundId);
        tempRound.setIsGenerate(GameConstants.IS_DELETE);
        tempRound.setIsArrange(reqChallenge.getIsArrange());
        tempRound.setStartTime(new Date(roundStartTime));
        tempRound.setEndTime(new Date(roundEndTime));
        bizGameSystemDao.updateTbGameRound(tempRound);
    }


    public List<GameSchedule> transferTbGameSchedule2GameSchedule(List<VDefinedGameSchedule> vDefinedGameSchedules, Integer teamType, TbGameRound curGameRound) throws InvocationTargetException, IllegalAccessException {
        if (null!=curGameRound && curGameRound.getIsGenerate().equals(GameConstants.IS_NOT_DELETE)) {
            TbGameRound tempRound = new TbGameRound();                              //更新轮次状态,对战表生产
            tempRound.setId(curGameRound.getId());
            tempRound.setIsGenerate(GameConstants.IS_DELETE);
            bizGameSystemDao.updateTbGameRound(tempRound);

            officialGameCache.delGameRound(curGameRound.getId());
            logger.info("轮次id:{}的轮次更新,清空当前轮次", curGameRound.getId());
        }

        List<GameSchedule> gameSchedules = new ArrayList<>();
        if (null == vDefinedGameSchedules || vDefinedGameSchedules.size() < 1) {
            return null;
        }


        Set<Integer> gameScheduleIdSet = new HashSet<>();
        for (VDefinedGameSchedule vDefinedGameSchedule : vDefinedGameSchedules) {
            gameScheduleIdSet.add(vDefinedGameSchedule.getGameScheduleId());
        }
        for (Integer temp : gameScheduleIdSet) {
            gameSchedules.add(officialGameCache.getGameSchedule(temp, (byte)teamType.intValue()));
        }

        //按id升序排列
        Collections.sort(gameSchedules, new Comparator<GameSchedule>() {
            public int compare(GameSchedule o1, GameSchedule o2) {
                return o1.getId().compareTo(o2.getId());
            }
        });
        return gameSchedules;
    }

    @Override
    public List<GameGroupNumAndRankNum> getGroupNmAndRankNumByTeamNum(Integer teamNum) {
        int x = teamNum;
        List<Integer> rankList = new ArrayList<>();
        rankList.add(1);
        rankList.add(2);
        List<Integer> groups = new ArrayList<>();
        switch (x<1025?(x<513?(x<257?(x<192?(x<129?(x<97?(x<65?(x<49?(x<33?(x<25?(x<17?(x<13?(x<9?(x<5?(11):10):9):8):7):6):5):4):3):2):1):14):13):12):-1) {

            case (1):
                groups.add(32);
                groups.add(64);
                break;
            case (2):
                groups.add(32);
                break;
            case (3):
                groups.add(16);
                groups.add(32);
                break;
            case (4):
                groups.add(16);
                break;
            case (5):
                groups.add(8);
                groups.add(16);
                break;
            case (6):
                groups.add(8);
                break;
            case (7):
                groups.add(4);
                groups.add(8);
                break;
            case (8):
                groups.add(4);
                break;
            case (9):
                groups.add(2);
                groups.add(4);
                break;
            case (10):
                groups.add(2);
                break;
            case (11):
                groups.add(2);
                groups.add(4);
                break;
            case (12):
                groups.add(128);
                groups.add(256);
                break;
            case (13):
                groups.add(64);
                groups.add(128);
                break;
            case (14):
                groups.add(32);
                groups.add(64);
                break;
            case (-1):
                groups.add(128);
                groups.add(256);
                break;
            default:
                break;
        }
        List<GameGroupNumAndRankNum> result = new ArrayList<>();
        for (Integer integer : groups) {
            Map<Integer, Integer> rankProductMap = new HashMap<>();
            GameGroupNumAndRankNum gameGroupNumAndRankNum = new GameGroupNumAndRankNum();
            gameGroupNumAndRankNum.setRankNumList(rankList);
            gameGroupNumAndRankNum.setGroupNum(integer);
            rankProductMap.put(1, this.getProductsByGroup(teamNum, integer, 1));
            rankProductMap.put(2, this.getProductsByGroup(teamNum, integer, 2));
            gameGroupNumAndRankNum.setRankProductMap(rankProductMap);
            result.add(gameGroupNumAndRankNum);
        }
        return result;
    }

    @Override
    public void updateTimeAndUnit(Integer curGameRoundId, ReqChallenge reqChallenge) {
        TbGameRound tbGameRound = bizGameSystemDao.selectTbGameRound(curGameRoundId);
        //对战表未生成时,但轮次数据已存在的情况下;
        if (null!=tbGameRound && tbGameRound.getIsGenerate().intValue() == GameConstants.IS_NOT_DELETE.intValue()) {
            this.updateScheduleTimeAndPlaceUnit(curGameRoundId, reqChallenge);
        }
    }

    @Override
    public Map<Integer, List<GameSchedule>> generateCompListV2(ReqChallenge reqChallenge) throws Exception {
        Map<Integer, List<GameSchedule>> result = new HashMap<>();
        reqChallenge.setGameRoundId(reqChallenge.getGameRoundId());
        result.put(reqChallenge.getGameRoundId(), generateCompList(reqChallenge));
        return result;
    }

    @Override
    public List<Integer> gameTeamIdTransferTeamIdNew(Integer gameScheduleId, List<Integer> oldTeamIds) {
        List<VDefinedGameSchedule> temp = bizGameSystemDao.selectVDefinedGameScheduleById(gameScheduleId);
        if (CollectionUtils.isNotEmpty(temp)) {
            if (temp.size() == 2) {
                return oldTeamIds;
            }else if (temp.size() == 4) {
                oldTeamIds = new ArrayList<>();
                for (VDefinedGameSchedule v : temp) {
                    if (v.getType().intValue() == GameConstants.IS_NOT_DELETE.intValue()) { //主场
                        oldTeamIds.add(0, v.getEventTeamId());
                    }else if (v.getType().intValue() == GameConstants.IS_DELETE.intValue()) {   //客场
                        oldTeamIds.add(oldTeamIds.size(), v.getEventTeamId());
                    }
                }
                return oldTeamIds;
            }
        }

        return null;
    }

    @Override
    public Map<Integer, Integer> gameTeamIdTransferTeamIdNew(Integer gameEventId) {
        Map<Integer, Integer> result = new HashMap<>();
        List<TbTeamDoubleAddendum> temp = bizGameSystemDao.queryTbTeamDoubleAddendumList(gameEventId);
        if (CollectionUtils.isNotEmpty(temp)) {
            for (TbTeamDoubleAddendum v : temp) {
                List<Integer> tempList =new Gson().fromJson(v.getTeamIdGson() ,new TypeToken<List<Integer>>() {
                }.getType());
                result.put(tempList.get(0), tempList.get(1));
                result.put(tempList.get(1), tempList.get(0));
            }
        }

        return result;
    }


    private int getProductsByGroup(Integer teamNum, Integer group, Integer rank){
        int washedProducts = GameUtils.washedScheduleNum(group.doubleValue() * rank);
        int circleProductsSimple = (group-1) * GameUtils.circleScheduleNum((double) (teamNum / group));
        int circleProductsUnique = GameUtils.circleScheduleNum((double) (teamNum / group + teamNum % group));
        return  washedProducts + circleProductsSimple + circleProductsUnique;
    }

    private void transferTbGameSchedule2GameScheduleInitParam(List<GameSchedule> gameSchedules, Map<Integer, List<VDefinedGameSchedule>> mapSchedules, Integer teamType,
                                                              Map<Integer, RespClubPlainInfo> mapClubIdMap, Map<Integer, RespUserInfoBase> mapUidMap, Map<Integer, PlaceUnitInfo> placeUnitInfoMap) throws InvocationTargetException, IllegalAccessException {
        for (Map.Entry<Integer, List<VDefinedGameSchedule>> entry : mapSchedules.entrySet()) {
            GameSchedule gameSchedule = new GameSchedule();
            gameSchedule.setId(entry.getKey());
            GameTeam gameTeam = new GameTeam();
            GameTeam gameTeam1 = new GameTeam();
            List<VDefinedGameSchedule> listTemp = entry.getValue();
            List<User> users1 = new ArrayList<>();
            List<User> users2 = new ArrayList<>();
            for (VDefinedGameSchedule vDefinedGameSchedule : listTemp) {
                if (null != vDefinedGameSchedule.getFinalScore()) {
                    gameSchedule.setScore(vDefinedGameSchedule.getFinalScore());
                }
                if (null != vDefinedGameSchedule.getPlaceUnitId()) {
                    gameSchedule.setPlaceUnitInfo(placeUnitInfoMap.get(vDefinedGameSchedule.getPlaceUnitId()));
                }
                if (null != vDefinedGameSchedule.getStatus()) {
                    gameSchedule.setRecordStatus(vDefinedGameSchedule.getStatus());
                }

                if (null != vDefinedGameSchedule.getStartTime()) {
                    gameSchedule.setStartTime(vDefinedGameSchedule.getStartTime().getTime());
                }
                if (null != vDefinedGameSchedule.getEndTime()) {
                    gameSchedule.setEndTime(vDefinedGameSchedule.getEndTime().getTime());
                }
                gameSchedule.setIsWin(vDefinedGameSchedule.getIsWin());
                gameSchedule.setPlaceUnitInfo(placeUnitInfoMap.get(vDefinedGameSchedule.getPlaceUnitId()));
                gameSchedule.setRoundId(vDefinedGameSchedule.getGameRoundId());
                gameSchedule.setGroup(vDefinedGameSchedule.getGroup());    //获取分组,适用于混合赛
                gameTeam.setType(teamType.byteValue());
                gameTeam1.setType(teamType.byteValue());
                if (GameConstants.TEAM_TYPE_CLUB == teamType.byteValue()) {
                    if (vDefinedGameSchedule.getType() == 0) {
                        gameTeam.setId(vDefinedGameSchedule.getEventTeamId());
                        Club club = new Club();
                        if (null !=  mapClubIdMap.get(vDefinedGameSchedule.getClubId()) && mapClubIdMap.get(vDefinedGameSchedule.getClubId()).getClubId()>0) {
                            BeanUtils.copyProperties(club,  mapClubIdMap.get(vDefinedGameSchedule.getClubId()));
                        }
                        gameTeam.setClub(club);
                    }else if (vDefinedGameSchedule.getType() == 1) {
                        gameTeam1.setId(vDefinedGameSchedule.getEventTeamId());
                        Club club = new Club();
                        if (null !=  mapClubIdMap.get(vDefinedGameSchedule.getClubId()) && mapClubIdMap.get(vDefinedGameSchedule.getClubId()).getClubId()>0) {
                            BeanUtils.copyProperties(club,  mapClubIdMap.get(vDefinedGameSchedule.getClubId()));
                        }
                        gameTeam1.setClub(club);
                    }
                }else if (GameConstants.TEAM_TYPE_PERSON == teamType.byteValue()) {
                    if (vDefinedGameSchedule.getType() == 0) {
                        gameTeam.setId(vDefinedGameSchedule.getEventTeamId());
                        User user = new User();
                        if (null !=  mapUidMap.get(vDefinedGameSchedule.getUid()) && mapUidMap.get(vDefinedGameSchedule.getUid()).getUid()>0) {
                            BeanUtils.copyProperties(user,  mapUidMap.get(vDefinedGameSchedule.getUid()));
                        }
                        users1.add(user);
                    }else if (vDefinedGameSchedule.getType() == 1) {
                        gameTeam1.setId(vDefinedGameSchedule.getEventTeamId());
                        User user = new User();
                        if (null !=  mapUidMap.get(vDefinedGameSchedule.getUid()) && mapUidMap.get(vDefinedGameSchedule.getUid()).getUid()>0) {
                            BeanUtils.copyProperties(user,  mapUidMap.get(vDefinedGameSchedule.getUid()));
                        }
                        users2.add(user);
                    }
                }else {
                }
            }
            gameTeam.setUserList(users1);
            gameTeam1.setUserList(users2);
            if ((null != users1 && users1.size() > 0) || null != gameTeam.getClub()) {
                gameSchedule.setHomeGameTeam(gameTeam);
            }
            if ((null != users2 && users2.size() > 0) || null != gameTeam1.getClub()) {
                gameSchedule.setAwayGameTeam(gameTeam1);
            }
            gameSchedule.setCurTime(new Date().getTime());
            gameSchedules.add(gameSchedule);
        }
    }

    /**
     * 说明:淘汰赛的对战表,无法一次性生成,只能依赖上一轮的得胜队伍
     * 注意淘汰赛的第一轮,必须利用规则将多余的队伍更新,轮空
     *
     *
     * */
    private List<VDefinedGameSchedule> generateWashedCompList(List<TbGameRound> tbGameRoundList, List<Integer> teamIs, ReqChallenge reqChallenge, Integer preGameRoundId) {
        logger.info("开始生成淘汰赛对战表,当前轮次ID:{}", reqChallenge.getGameRoundId());
        Integer currentGameRoundId = reqChallenge.getGameRoundId();
        List<VDefinedGameSchedule> curDefinedGameSchedules = bizGameSystemDao.selectVDefinedGameScheduleByGameRoundId(currentGameRoundId, null, null);
        if (curDefinedGameSchedules!=null && curDefinedGameSchedules.size() >0) {
           // this.updateTimeAndUnit(currentGameRoundId, reqChallenge);
            return curDefinedGameSchedules;
        }
        List<GameGroup> gameGroups = new ArrayList<>();
        GameGroup gameGroup = new GameGroup();
        gameGroup.setGameRoundId(currentGameRoundId);
        int i = 0;
        for (TbGameRound tbGameRound : tbGameRoundList) {
            if ((tbGameRound.getId().compareTo(currentGameRoundId)) == 0) {
                if (0 == i) { //第一轮淘汰赛处理
                    Collections.shuffle(teamIs);    //淘汰赛洗牌模式
                    gameGroups = gameSystemService.washedGroup(this.transferTeamIdToDoubleTeam(reqChallenge, new ArrayList(teamIs)), tbGameRound, true);
                } else {
                    List<VDefinedGameSchedule> preGamSchedules = bizGameSystemDao.selectVDefinedGameScheduleByGameRoundId(preGameRoundId, null, null);
                    if (null == preGamSchedules || preGamSchedules.size() < 1) {
                        return curDefinedGameSchedules;
                    }
                    Set<Integer> teamIds = new HashSet<>();
                    for (VDefinedGameSchedule vDefinedGameSchedule:preGamSchedules) {
                        if (vDefinedGameSchedule.getIsWin() == GameConstants.SCHEDULE_WIN && vDefinedGameSchedule.getType() == 0) {  //主场胜利
                            teamIds.add(vDefinedGameSchedule.getEventTeamId());
                        }else if (vDefinedGameSchedule.getIsWin() == GameConstants.SCHEDULE_LOSE && vDefinedGameSchedule.getType() == 1) { //客场胜利
                            teamIds.add(vDefinedGameSchedule.getEventTeamId());
                        }else {
                        }
                    }
                    gameGroups = gameSystemService.washedGroup(this.transferTeamIdToDoubleTeam(reqChallenge, new ArrayList(teamIds)), tbGameRound, false);
                }
                break;
            }
            i++;
        }
        return this.generateScheduleAndUpdateRound(0, gameGroups, currentGameRoundId, reqChallenge);
    }

    /**
     * 说明:单循环赛的对战可以一次性,全部生成
     *
     *
     * */
    private List<VDefinedGameSchedule> generateCircleCompList(List<TbGameRound> tbGameRoundList, List<Integer> teamIds, ReqChallenge reqChallenge, Integer teamType) {
        logger.info("开始生成循环赛对战表,当前轮次ID:{}", reqChallenge.getGameRoundId());
        Integer currentGameRoundId = reqChallenge.getGameRoundId();
        List<VDefinedGameSchedule> currentGameSchedules = bizGameSystemDao.selectVDefinedGameScheduleByGameRoundId(currentGameRoundId, null, null);
        if (currentGameSchedules!=null && currentGameSchedules.size() >0) {
            this.updateTimeAndUnit(currentGameRoundId, reqChallenge);
            return currentGameSchedules;
        }
        List<GameGroup> gameGroups = gameSystemService.circleGroup(this.transferTeamIdToDoubleTeam(reqChallenge, teamIds), tbGameRoundList, 0, teamType);
        return this.generateScheduleAndUpdateRound(0, gameGroups, currentGameRoundId, reqChallenge);
    }

    /**
     * 说明:瑞士赛(等位赛),类似一种单循环和淘汰赛,当前这一轮的依赖于上一轮的分数,然后按照大分数,一次类推
     *
     *
     * */
    private List<VDefinedGameSchedule> generateSwissCompList(List<TbGameRound> tbGameRoundList, List<Integer> teamIds, ReqChallenge reqChallenge, Integer preGameRoundId) {
        logger.info("开始生成瑞士赛对战表,当前轮次ID:{}", reqChallenge.getGameRoundId());
        Integer currentGameRoundId = reqChallenge.getGameRoundId();
        List<VDefinedGameSchedule> currentGameSchedules = bizGameSystemDao.selectVDefinedGameScheduleByGameRoundId(currentGameRoundId, null, null);
        if (currentGameSchedules!=null && currentGameSchedules.size() >0) {
            this.updateTimeAndUnit(currentGameRoundId, reqChallenge);
            return currentGameSchedules;
        }
        currentGameSchedules = new ArrayList<>();
        List<GameGroup> gameGroups = new ArrayList<>();
        GameGroup gameGroup = new GameGroup();
        gameGroup.setGameRoundId(currentGameRoundId);
        int i = 0;
        for (TbGameRound tbGameRound : tbGameRoundList) {
            if ((tbGameRound.getId().compareTo(currentGameRoundId)) == 0) {
                if (0 == i) {
                    Collections.shuffle(teamIds);   //等位制加入洗牌模式
                    gameGroups = gameSystemService.swissGroupNew(this.transferTeamIdToDoubleTeam(reqChallenge, teamIds), tbGameRound, null, true);
                } else {
                    List<TbGameSchedule> preGamSchedules = bizGameSystemDao.selectTbGameScheduleByGameRoundId(preGameRoundId, null, null);
                    if (null == preGamSchedules || preGamSchedules.size() < 1) {
                        return currentGameSchedules;
                    }
                    List<TbGameRoundScore> tbGameRoundScoreList = bizGameSystemDao.selectTbGameRoundScoreByGameRoundId(preGameRoundId, null,null);
                    if (null == tbGameRoundScoreList) {
                        return currentGameSchedules;
                    }
                    List<Integer> teamTempIds = new ArrayList<>();
                    for (TbGameRoundScore tbGameRoundScore:tbGameRoundScoreList) {
                        teamTempIds.add(tbGameRoundScore.getGameEventTeamId());
                    }
                    gameGroups = gameSystemService.swissGroupNew(this.transferTeamIdToDoubleTeam(reqChallenge, teamTempIds), tbGameRound, preGameRoundId, false);
                }
                break;
            }
            i++;
        }
        return this.generateScheduleAndUpdateRound(0, gameGroups, currentGameRoundId, reqChallenge);
    }

    /**
     * 说明:混合赛,分组积分循环赛+淘汰赛  (不支持双打)
     *
     *
     * */
    private List<VDefinedGameSchedule> generateMixedCompList(List<TbGameRound> tbGameRoundList, List<Integer> teamIds, ReqChallenge reqChallenge, Integer preGameRoundId) {
        logger.info("开始生成混合赛对战表,当前轮次ID:{}", reqChallenge.getGameRoundId());
        Integer currentGameRoundId = reqChallenge.getGameRoundId();
        List<VDefinedGameSchedule> currentGameSchedules = bizGameSystemDao.selectVDefinedGameScheduleByGameRoundId(currentGameRoundId, null, null);
        if (currentGameSchedules != null && currentGameSchedules.size() > 0) {
            this.updateTimeAndUnit(currentGameRoundId, reqChallenge);
            return currentGameSchedules;
        }
        TbGameEvent tbGameEvent = bizGameSystemDao.selectTbGameEvent(tbGameRoundList.get(0).getGameEventId());
        List<GameGroup> gameGroups = new ArrayList<>();
        List<TbGameRound> circleGameRoundList = new ArrayList<>();
        List<TbGameRound> washedGameRoundList = new ArrayList<>();
        TbGameRound curTbGameRound = new TbGameRound();
        int circleRoundNum = GameUtils.circleRoundNum((double) (teamIds.size() % tbGameEvent.getTeamGroupNum() + teamIds.size() / tbGameEvent.getTeamGroupNum()));
        for (int j = 0; j < tbGameRoundList.size(); j++) {
            if (tbGameRoundList.get(j).getId().equals(currentGameRoundId)) {
                curTbGameRound = tbGameRoundList.get(j);
            }
            if (circleRoundNum < j + 1) {
                washedGameRoundList.add(tbGameRoundList.get(j));
            } else {
                circleGameRoundList.add(tbGameRoundList.get(j));
            }
        }
        //验证循环对阵是否创建
        List<TbGameSchedule> circleGameSchedules = bizGameSystemDao.selectTbGameScheduleByGameRoundId(circleGameRoundList.get(0).getId(), null, null);
        if (null != circleGameSchedules && circleGameSchedules.size() > 0) {
            List<TbGameSchedule> washedGameSchedules = bizGameSystemDao.selectTbGameScheduleByGameRoundId(washedGameRoundList.get(0).getId(), null, null);
            List<Integer> teamTempIds = new ArrayList<>();
            if (washedGameSchedules.size() > 0) {
                //混合赛-淘汰赛第一场
                Set<Integer> tempIds = new HashSet<>();
                List<VDefinedGameSchedule> preGameSchedules = bizGameSystemDao.selectVDefinedGameScheduleByGameRoundId(preGameRoundId, null, null);
                for (VDefinedGameSchedule vDefinedGameSchedule : preGameSchedules) {
                    if (vDefinedGameSchedule.getIsWin() == GameConstants.SCHEDULE_WIN && vDefinedGameSchedule.getType() == 0) {  //主场胜利
                        tempIds.add(vDefinedGameSchedule.getEventTeamId());
                    }else if (vDefinedGameSchedule.getIsWin() == GameConstants.SCHEDULE_LOSE && vDefinedGameSchedule.getType() == 1) { //客场胜利
                        tempIds.add(vDefinedGameSchedule.getEventTeamId());
                    }else {
                    }
                }
                gameGroups = gameSystemService.washedGroup(new ArrayList<Integer>(tempIds), curTbGameRound, false);
            } else {
                //淘汰第一场,获取分组循环赛的最后一轮集合; 并加入随机打乱分组
                int rankNum = tbGameEvent.getRankNum();
                Integer lastCircleRoundId = circleGameRoundList.get(circleGameRoundList.size() -1).getId();
                List<TbGameRoundScore> list = bizGameSystemDao.selectTbGameRoundScoreByGameRoundId(lastCircleRoundId, 0, teamIds.size());
                Map<Integer, List<TbGameRoundScore>> mapTemp = new HashMap<>();
                Set<Integer> groupSet = new HashSet<>();
                for (TbGameRoundScore tbGameRoundScore : list) {
                    List<TbGameRoundScore> setTemp = mapTemp.get(tbGameRoundScore.getGroupType().intValue());
                    if (null == setTemp || setTemp.size() < 1) {
                        setTemp = new ArrayList<>();
                    }
                    setTemp.add(tbGameRoundScore);
                    mapTemp.put(tbGameRoundScore.getGroupType().intValue(), setTemp);
                    groupSet.add(tbGameRoundScore.getGroupType().intValue());
                }
                List<Integer> tempRandomList = new ArrayList<>(groupSet);
                Collections.shuffle(tempRandomList);
                for (Integer tempInt : tempRandomList) {
                    //按score降序排列
                    List<TbGameRoundScore> roundScores = mapTemp.get(tempInt);
                    Collections.sort(roundScores, new Comparator<TbGameRoundScore>() {
                        public int compare(TbGameRoundScore o1, TbGameRoundScore o2) {
                            return o2.getScore().compareTo(o1.getScore());
                        }
                    });
                    for (int i=0;i<rankNum;i++) {
                        teamTempIds.add(roundScores.get(i).getGameEventTeamId());
                    }
                }
                gameGroups = gameSystemService.washedGroup(teamTempIds, curTbGameRound, true);
            }
        } else {
            Collections.shuffle(teamIds);    //混合赛的分组之前对队伍进行洗牌模式
            int teamNum = teamIds.size();  //队伍数目
            int m = teamNum%tbGameEvent.getTeamGroupNum();   //缺省的人数
            int n = teamNum/tbGameEvent.getTeamGroupNum();  //每组人数
            //生成循环赛,按组
            for (int k=0;k<tbGameEvent.getTeamGroupNum();k++) {
                if (k ==0 && m>0) {
                    gameGroups.addAll(gameSystemService.circleGroup(teamIds.subList(0, m + n), circleGameRoundList, k+1, tbGameEvent.getGameTeamType().intValue()));
                }else {
                    gameGroups.addAll(gameSystemService.circleGroup(teamIds.subList(m+n*k, n+m+n*k), circleGameRoundList, k+1, tbGameEvent.getGameTeamType().intValue()));
                }
            }
        }
       return this.generateScheduleAndUpdateRound(0, gameGroups, currentGameRoundId, reqChallenge);
    }

    /**
     * 说明:百灵鸟羽毛球8人打球,
     *
     *
     * */
    private List<VDefinedGameSchedule> generateEightCompList(List<Integer> teamIds, ReqChallenge reqChallenge, Integer preGameRoundId) {
        logger.info("开始生成百灵鸟羽毛球8人制对战表,当前轮次ID:{}", reqChallenge.getGameRoundId());
        Integer currentGameRoundId = reqChallenge.getGameRoundId();
        List<VDefinedGameSchedule> currentGameSchedules = bizGameSystemDao.selectVDefinedGameScheduleByGameRoundId(currentGameRoundId, null, null);
        if (currentGameSchedules != null && currentGameSchedules.size() > 0) {
            this.updateTimeAndUnit(currentGameRoundId, reqChallenge);
            return currentGameSchedules;
        }
        gameSystemServiceEight.initEightRound(this.transferTeamIdToDoubleTeam(reqChallenge, teamIds), currentGameRoundId, preGameRoundId);
        return this.generateScheduleAndUpdateRound(1, null, currentGameRoundId, reqChallenge);
    }

    /**
     * 说明:百灵鸟网球5-8人打球,
     *
     *
     * */
    private List<VDefinedGameSchedule> generateUnsetCompList(List<Integer> teamIds, ReqChallenge reqChallenge, Integer preGameRoundId) {
        logger.info("开始生成百灵鸟网球5-8制对战表,当前轮次ID:{}", reqChallenge.getGameRoundId());
        Integer currentGameRoundId = reqChallenge.getGameRoundId();
        List<VDefinedGameSchedule> currentGameSchedules = bizGameSystemDao.selectVDefinedGameScheduleByGameRoundId(currentGameRoundId, null, null);
        if (currentGameSchedules != null && currentGameSchedules.size() > 0) {
            this.updateTimeAndUnit(currentGameRoundId, reqChallenge);
            return currentGameSchedules;
        }
        gameSystemServiceUnset.initUnSetGameRound(this.transferTeamIdToDoubleTeam(reqChallenge, teamIds), currentGameRoundId, preGameRoundId);
        return this.generateScheduleAndUpdateRound(1, null, currentGameRoundId, reqChallenge);
    }

    /**
     * 双打的时候队伍逻辑转化,
     *
     * 需要注意: 淘汰人数递减\循环+等位人数不变的 比较逻辑
     *
     *
     * */
    private List<Integer> transferTeamIdToDoubleTeam(ReqChallenge reqChallenge, List<Integer> teamIds){
        if (reqChallenge.getGameSystemType().intValue() == GameSystemConfigEnum.CONFIG_GAME_TYPE_EIGHT_RULE.getId() ||
                reqChallenge.getGameSystemType().intValue() == GameSystemConfigEnum.CONFIG_GAME_TYPE_UNSET_RULE.getId()) {
            return teamIds;
        }
        List<TbTeamDoubleAddendum> addendums = reqChallenge.getTbTeamDoubleAddendumList();
        if (null == addendums || addendums.size() < 1) {
            return teamIds;
        }
        int maxGroupNum = teamIds.size()/2;
        Gson gson = new Gson();
        List<Integer> newTeams = new ArrayList<>();
        while (newTeams.size() < maxGroupNum) {
            for (TbTeamDoubleAddendum tbTeamDoubleAddendum : addendums) {
                List<Integer> tempList =gson.fromJson(tbTeamDoubleAddendum.getTeamIdGson() ,new TypeToken<List<Integer>>() {
                }.getType());
                if (teamIds.size()>0 && tempList.contains(teamIds.get(0))) {
                    teamIds.removeAll(tempList);
                    newTeams.add(tbTeamDoubleAddendum.getId());
                }
            }
        }
        return newTeams;
    }


    /**
     * 是否需要分组,根据分项目和赛制
     * */
    private boolean isDivideTeam(TbGameEvent tbGameEvent){
        //8人抢签位\ 不固定打发不需要分组
        if (tbGameEvent.getGameSystemType().intValue() == GameSystemConfigEnum.CONFIG_GAME_TYPE_EIGHT_RULE.getId() ||
                tbGameEvent.getGameSystemType().intValue() == GameSystemConfigEnum.CONFIG_GAME_TYPE_UNSET_RULE.getId()) {
            return false;
        }else {
            if (gameEventTransfer.getGameCategoryById(tbGameEvent.getGameCategoryType().intValue()).getMinNum() == 2
                    && gameEventTransfer.getGameCategoryById(tbGameEvent.getGameCategoryType().intValue()).getMaxNum() == 2) {
                    return true;
            }
        }
        return false;
    }
}
